package stone926.mods.more_enchantments.mixins;

import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.projectile.ExplosiveProjectileEntity;
import net.minecraft.entity.projectile.WitherSkullEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import stone926.mods.more_enchantments.interfaces.IWitherSkull;

import static stone926.mods.more_enchantments.nbt.CustomNbtKeys.WITHER_SKULL.*;

@Mixin(WitherSkullEntity.class)
public class WitherSkullEntityMixin extends ExplosiveProjectileEntity implements IWitherSkull {

  private float drag = 0.95F;
  private boolean dragModified = false;
  private float extraDamage = 0F;
  private boolean strengthened = false;

  protected WitherSkullEntityMixin(EntityType<? extends ExplosiveProjectileEntity> entityType, World world) {
    super(entityType, world);
  }

  @Override
  public void writeCustomDataToNbt(NbtCompound nbt) {
    super.writeCustomDataToNbt(nbt);
    nbt.putBoolean(DRAG_MODIFIED, dragModified);
    nbt.putFloat(DRAG, drag);
    nbt.putFloat(EXTRA_DAMAGE, getExtraDamage());
    nbt.putBoolean(STRENGTHENED, getStrengthened());
  }

  @Override
  public void readCustomDataFromNbt(NbtCompound nbt) {
    super.readCustomDataFromNbt(nbt);
    if (nbt.contains(DRAG_MODIFIED)) dragModified = nbt.getBoolean(DRAG_MODIFIED);
    if (nbt.contains(DRAG)) drag = nbt.getFloat(DRAG);
    if (nbt.contains(EXTRA_DAMAGE)) setExtraDamage(nbt.getFloat(EXTRA_DAMAGE));
    if (nbt.contains(STRENGTHENED)) setStrengthened(nbt.getBoolean(STRENGTHENED));
  }

  @Inject(method = "getDrag", at = @At("HEAD"), cancellable = true)
  private void getDrag1(CallbackInfoReturnable<Float> cir) {
    if (dragModified()) cir.setReturnValue(getModifiedDrag());
  }

  @Redirect(method = "onEntityHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;damage(Lnet/minecraft/entity/damage/DamageSource;F)Z"))
  protected boolean onEntityHit(Entity instance, DamageSource source, float amount) {
    boolean damage;
    if (getStrengthened()) {
      instance.timeUntilRegen = 0;
      if (instance instanceof LivingEntity livingEntity) {livingEntity.hurtTime = 0;}
    }
    damage = instance.damage(source, amount + getExtraDamage());
    if (getStrengthened()) {
      instance.timeUntilRegen = 0;
      if (instance instanceof LivingEntity livingEntity) {livingEntity.hurtTime = 0;}
    }
    return damage;
  }

  @Override
  public void setDrag(float d) {
    this.drag = d;
    dragModified = true;
  }

  @Override
  public float getModifiedDrag() {
    return drag;
  }

  @Override
  public boolean dragModified() {
    return dragModified;
  }

  @Override
  public float getExtraDamage() {
    return extraDamage;
  }

  @Override
  public void setExtraDamage(float extraDamage) {
    this.extraDamage = extraDamage;
  }

  @Override
  public boolean getStrengthened() {
    return strengthened;
  }

  @Override
  public void setStrengthened(boolean strengthened) {
    this.strengthened = strengthened;
  }

}
